home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
archiver
/
restore.arc
/
RESTORE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-01-07
|
12KB
|
387 lines
/*
*----------------------------------------------------------------------------
*
* RESTORE.C : a backup restorer for the Atari ST series
*
* This code was written to complement the very useful `Turtle'
* hard disk backup utility. It essentially does a `cp -r', maintaining
* the time stamps on files. It will create directories as needed
* on the receiving filesystem.
*
* This code is copyright (C) by Ross Alexander, Athabasca University,
* 1988. It may be freely redistributed and/or modified as long as:
* 1) This notice appears, &
* 2) modifications are noted as NOT my work.
*
* I think this programme is OK, but I take no responsibility for
* any result (or lack thereof...) of using it. Caveat Emptor.
*
* Basic Algorithm:
*
* open source directory
* count entries, reserve that much memory
* reopen source directory, read into memory
* sort alphabetically, moving directories to head
* of the list.
* conditionally create target directory
* call self for all directories in list
* copy all files in list to target, correcting time stamps
* release memory for list
*
*----------------------------------------------------------------------------
*/
#include <osbind.h>
#include <stat.h>
#include <stdio.h>
#include <ctype.h>
#define CANDIDATES ( S_IJRON | S_IJHID | S_IJSYS | S_IJDIR | S_IJWAC )
#define NULLPTR ( (char *) 0 )
extern char * malloc();
extern char * strcpy();
/* this is the stuff at the end of a DMABUFFER */
typedef struct {
char f_fattr; /* File attributes */
long f_tandd; /* Time and date words */
long f_fsize; /* File size */
char f_fname[14]; /* File name */
} FILEINFO;
/* this is a big enough buffer to do most files in a gulp */
#define BUFFER_SIZE 16384 /* utterly arbitrary */
char track_buffer[ BUFFER_SIZE ];
int v_flag = 0; /* verbosity flag */
/*
*----------------------------------------------------------------------------
*
* make a (longer) path name from a path-name and {dir,file}-name components
*
*----------------------------------------------------------------------------
*/
char * dircat( path, name )
char * path;
char * name;
{
int path_len = strlen( path );
char path_buf[ 128 ]; /* _should_ be lots... */
char * scan = path_buf;
strcpy( path_buf, path );
if ( path_len != 0 && path[ path_len - 1 ] != '\\' )
strcat( path_buf, "\\" );
strcat( path_buf, name );
while ( * scan ) {
if ( isupper( * scan ) ) * scan = tolower( * scan );
++ scan;
}
return strcpy( malloc( strlen( path_buf ) + 1 ), path_buf );
}
/*
*----------------------------------------------------------------------------
*
* count how many entries exist in a directory. ignores volume labels, ., ..
*
*----------------------------------------------------------------------------
*/
int get_dir_size( from )
char * from; /* source pathname */
{
DMABUFFER examine; /* place to hold these for counting */
int status; /* temp to hold Fs{first|next} value*/
DMABUFFER * old_dta = (DMABUFFER *) Fgetdta();
char * globname = dircat( from, "*.*" );
int list_length = 0;
Fsetdta( & examine ); /* read'em here, avoid buss faults! */
for ( status = Fsfirst( globname, CANDIDATES );
status == 0;
status = Fsnext() )
if ( examine.d_fname[ 0 ] != '.' )
++ list_length; /* ignore ., .. */
Fsetdta( old_dta );
free( globname ); /* don't need this any more */
return list_length;
}
/*
*----------------------------------------------------------------------------
*
* compare two directory entries; subdirectories sort ahead of files
*
*----------------------------------------------------------------------------
*/
static int dir_comp( a, b )
FILEINFO * a;
FILEINFO * b;
{
int attr_a = a->f_fattr & S_IJDIR;
int attr_b = b->f_fattr & S_IJDIR;
if ( attr_a != attr_b )
return attr_a ? -1 : 1; /* directories-ahead-of-files */
else
return strcmp( a->f_fname, b->f_fname );
}
/*
*----------------------------------------------------------------------------
*
* suck in a directory, sort it, return -> entries
*
*----------------------------------------------------------------------------
*/
FILEINFO * read_sorted_dir( path, length )
char * path;
int length;
{
FILEINFO * list = (FILEINFO *) malloc( length * sizeof (FILEINFO) );
FILEINFO * scan = list;
char * globname = dircat( path, "*.*" );
DMABUFFER * old_dta = (DMABUFFER *) Fgetdta();
DMABUFFER examine;
int status;
Fsetdta( & examine ); /* read'em here, avoid buss faults! */
for ( status = Fsfirst( globname, CANDIDATES );
status == 0;
status = Fsnext() )
if ( examine.d_fname[ 0 ] != '.' ) {
scan->f_fattr = examine.d_fattr;
scan->f_tandd = examine.d_tandd;
scan->f_fsize = examine.d_fsize;
strcpy( scan->f_fname, examine.d_fname );
++ scan;
}
qsort( list, length, sizeof (FILEINFO), dir_comp );
free( globname );
Fsetdta( old_dta );
return list;
}
/*
*----------------------------------------------------------------------------
*
* copy a file from `from' to `to_path\to_name', in a careful way.
*
*----------------------------------------------------------------------------
*/
char * copy_file( from, to_path, to_name )
char * from;
char * to_path;
char * to_name;
{
DMABUFFER * old_dta = (DMABUFFER *) Fgetdta();
char * to = dircat( to_path, to_name );
char * tmp = dircat( to_path, "$$$$$$$$.$$$" );
char * ret_msg = NULLPTR;
struct stat stat_from;
struct stat stat_to;
int from_h = -1;
int to_h = -1;
int dest_exists;
long chunk;
int timestamp[ 2 ];
if ( v_flag )
fprintf( stderr, "\t%s ==> %s\n", from, to );
/* check existence & modes of source */
if ( stat( from, & stat_from ) == NODEV ) {
ret_msg = "can't stat source";
goto exit;
}
/* check existence & type of destination */
if ( dest_exists = ( stat( to, & stat_to ) != NODEV ) ) {
if ( stat_to.st_mtime > stat_from.st_mtime ) {
ret_msg = "source older than destination";
goto exit;
} else if ( ( stat_to.st_mode & S_IJDIR ) != 0 ) {
ret_msg = "destination is directory";
goto exit;
}
}
/* open source file for reading */
from_h = Fopen( from, 0 );
if ( from_h < 0 ) {
ret_msg = "can't open input file";
goto exit;
}
/* create the temporary output file */
to_h = Fcreate( tmp, stat_from.st_mode );
if ( to_h < 0 ) {
ret_msg = "can't create temp file";
goto exit;
}
/* copy file contents across */
Fsetdta( track_buffer );
while ( stat_from.st_size > 0 ) {
chunk = stat_from.st_size > BUFFER_SIZE ?
BUFFER_SIZE : stat_from.st_size;
if ( chunk !=